<?php

namespace Biz\service\springHomeDecActivity;



use Biz\cache\lottery\CSpringHomeGift;
use Biz\cache\lottery\CSpringHomeLottery;
use Biz\cache\lottery\CSpringHomeVote;
use Biz\model\springHomeDecActivity\MSpringHomeDecBlackList;
use Biz\model\springHomeDecActivity\MSpringHomeDecProduct;
use Biz\model\springHomeDecActivity\MSpringHomeDecUserLottery;
use Biz\model\springHomeDecActivity\MSpringHomeDecWinningRecord;
use Biz\model\springHomeDecActivity\Wish as mWish;
use Biz\model\springHomeDecActivity\WishList;
use Doraemon\model\AdmUserType;
use Doraemon\model\DeviceBlackWhite;
use Doraemon\model\Member;
use Doraemon\service\DingTalkAlert;
use Doraemon\tools\HhzClient;
use Doraemon\tools\Ip;
use Doraemon\tools\Log;
use Exception;

class SSpringHomeDecLottery
{

    protected $_max_hit = 1;
    protected $_uid;
    protected $_complete;
    protected $_user_nick;
    protected $_user_identity_mark;
    protected $_user_quality;
    protected $_now;
    protected $_did;
    protected $_lock;
    protected $_gap_lock;
    protected $_activity_life = ['2022-03-21 00:00:00', '2022-04-01 23:59:59'];
    protected static $_day_times = 1;
    /**
     * @var MSpringHomeDecProduct
    */
    protected $_product; //中奖商品

    public function __construct($uid)
    {
        $this->_uid = $uid;
        $this->_did = HhzClient::getDid();
        $this->_now = date('Y-m-d H:i:s');
    }

    public function __destruct()
    {
        if ($this->_gap_lock) CSpringHomeGift::unlock($this->_gap_lock);
    }


    public function run(): array
    {
        $code = 1;
        $msg = '';
        $hit = null;
        $response = [
            'code' => &$code,
            'hit' => &$hit,
            'msg' => &$msg,
        ];
        try {
            // 获取用户信息
            $this->getUserInfo();

            //加锁
            $times = self::getUserLotteryTimes($this->_uid);
            if ($times <= 0) throw new Exception('抽奖次数不足1');
            //消耗抽奖次数
            if (CSpringHomeLottery::decrUserTimes($this->_uid) < 0) throw new Exception('抽奖次数不足2');

            // 过滤规则
            $this->rules();
            // 抽奖
            $this->lottery();
            // 扣除
            $this->record();
            // 返回中奖信息
            if ($this->_product) {
                $hit = [
                    'id' => $this->_product->product_id,
                    'is_virtual' => $this->_product->product_type == MSpringHomeDecProduct::PRODUCT_TYPE_SERVICE,
                    'name' => $this->_product->product_name,
                    'pic_url' => $this->_product->product_pic,
                    'winning_record_id' => $this->_product->winning_record_id,
                ];
                try {
                    $this->msg();
                } catch (Exception $e) {
                    $msg = '钉钉消息错误';
                    $real_msg = $e->getMessage();
                }
            }
        } catch (Exception $e) {
            $code = $e->getCode();
            $real_msg = $e->getMessage();
            $msg = '与奖品擦肩而过';
        }
        Log::info('家装节日志:抽奖', [
            'uid' => $this->_uid,
            'did' => $this->_did,
            'hit' => $hit,
            'now' => $this->_now,
            'msg' => $msg,
            'real_msg' => $real_msg ?? $msg,
        ]);
        return $response;
    }

    protected function getUserInfo()
    {
        $aMemberQualityInfo = AdmUserType::getByUid($this->_uid) ?: [];
        $this->_user_quality = $aMemberQualityInfo['quality'] ?? '';
        $this->_user_identity_mark = trim($aMemberQualityInfo['identity_mark'] ?? '');
        $this->_user_nick = Member::getNickByUid($this->_uid);
        $this->_complete = (bool)mWish::dataSelectInfo(['uid' => $this->_uid, 'data_status' => mWish::STATUS_NORMAL]);
    }

    /**
     * 规则限制
     * @throws Exception
     */
    protected function rules()
    {
        //2.1 活动时间的的控制
        if ($this->_now <= $this->_activity_life[0]) throw new Exception('抽奖活动未开始');
        if ($this->_now >= $this->_activity_life[1]) throw new Exception('抽奖活动未开始');
        //2.2 搭建完成
        if (!$this->_uid) throw new Exception('登录后才能抽奖');
        if (!$this->_complete) throw new Exception('搭建家完成之后才能抽奖');
        //2.3 注册时间 → 完成搭建阈值

        //2.4 用户类型 → 普通 + 个人V用户; B级用户、批量刷交互、设备批量注册、IP批量注册、批量注册、积分反垃圾、被拉黑的设备ID、测试账号、疑似商业用户、机器人账号、注册后没有修改过昵称的账号
        if ($this->_user_quality == AdmUserType::B1)  throw new Exception('B级用户');
        if (strpos($this->_user_nick, "住友_") !== false) throw new Exception('没有修改过昵称的账号');
        if (DeviceBlackWhite::selectByWhere([
            'device_id' => $this->_did,
            'data_type' => DeviceBlackWhite::DEVICE_BLACK_TYPE,
            'data_status' =>DeviceBlackWhite::STATUS_NORMAL,
        ])) throw new Exception('被拉黑的设备ID:' . $this->_did);
        if (strpos($this->_user_identity_mark, "批量") !== false) throw new Exception('批量标识的账号');
        if (strpos($this->_user_identity_mark, "测试账号") !== false) throw new Exception('测试账号');
        if (strpos($this->_user_identity_mark, "疑似商业用户") !== false) throw new Exception('疑似商业用户');
        if (strpos($this->_user_identity_mark, "机器人账号") !== false) throw new Exception('机器人账号');
        if (strpos($this->_user_identity_mark, "积分反垃圾") !== false) throw new Exception('积分反垃圾');
        //2.5 公司白名单
        if (in_array($this->_uid, \Biz\tools\helper\Common::getHhzWorkerUids())) throw new Exception('公司用户白单');
        //2.6 本次活动黑名单
        if (MSpringHomeDecBlackList::isBlack($this->_uid)) throw new Exception('本次活动黑名单');
        $ip = Ip::getClientIp();
        if ($ip == '220.194.45.131') throw new \Exception('排除公司ip');
    }

    /**
     * @throws Exception
     */
    public function lottery()
    {
        //奖品发放间隔控制,消耗或者不消耗
        if (!($this->_gap_lock = CSpringHomeGift::lock(30))) throw new Exception('奖品发放间隔控制');
        //随机心愿单商品
        $this->wish_products();
        if (empty($this->_product)) throw new Exception('心愿单商品或商品池为空');
        $this->_product = new MSpringHomeDecProduct($this->_product);
        //获取商品概率
        $rate = $this->rate();
        //获取是否已经抽奖
        $hits = MSpringHomeDecUserLottery::getUserLotteryHitTimes($this->_uid);
        if ($hits >= $this->_max_hit) throw new Exception('中奖次数已达上限,hits:' . $hits);
        if ($hits > 1) $rate = $rate / 2;

        //中奖概率
        if (!in_array(mt_rand(1, 1000), range(1, $rate))) $this->_product = null;
    }

    public function msg()
    {
        $token = '57e83d24a006edc904920f2ea3b9478b3f3d05593c93abbf8273789240c136db';
        $name = $this->_product->product_name;
        $value = $this->_product->product_value;
        $nick = $this->_user_nick;
        $uid = $this->_uid;
        $total = $this->_product->total;
        $num = $this->_product->num - 1;
        $markDownContent = <<<MSG
奖品出库情况通知 
奖品名称：$name
价值：$value
中奖用户：$nick  $uid
奖品库存余量：($num/$total)
MSG;
        DingTalkAlert::sendTextMsg($token, $markDownContent, true);
    }
    /**
     * 200元以下：中奖概率为20%
     * 201-500元：15%
     * 501-1000：10%
     * 1001-2000：8%
     * 2001-4000：5%
     * 4000以上：2%
    */
    protected function rate(): int
    {
        $value = $this->_product->product_value;
        $type = $this->_product->product_type;
        if ($type == MSpringHomeDecProduct::PRODUCT_TYPE_SERVICE) {
            return 600;
        }
        if ($value <= 200) {
            return 550;
        }
        if ($value <= 500) {
            return 500;
        }
        if ($value <= 1000) {
            return 350;
        }
        if ($value <= 2000) {
            return 300;
        }
        if ($value <= 4000) {
            return 250;
        }
        return 200;
    }

    public function record()
    {
        if (!$this->_product) throw new Exception('没有中奖');
        if (!CSpringHomeVote::incrDidLottery($this->_did, $this->_max_hit)) throw new Exception('设备中奖次数上限');
        MSpringHomeDecProduct::action(function () {
            $product_id = $this->_product->product_id;
            $v = MSpringHomeDecProduct::getV($this->_product->product_id);
            //1.扣除逻辑当前库存
            if (!CSpringHomeGift::decreaseGift($product_id)) throw new Exception('扣除缓存失败');
            //2.扣除商品清单总库存
            if (!MSpringHomeDecProduct::decreaseStock($product_id, $v)) throw new Exception('扣除商品清单总库存失败');
            //3.记录中奖统计
            $v = MSpringHomeDecUserLottery::getV($this->_uid);
            if (!MSpringHomeDecUserLottery::addRecord($this->_uid, $v, $this->_max_hit)) throw new Exception('生成中奖统计失败');
            //4.记录抽奖记录
            if (!($this->_product->winning_record_id = MSpringHomeDecWinningRecord::addRecord($this->_uid, $product_id, $this->_product->product_type))) throw new Exception('生成抽奖记录失败');
            //5.记录心愿单
            if (!WishList::increaseWinning($this->_uid, $product_id)) throw new Exception('心愿单更新失败');
        });

    }

    public function wish_products()
    {
        // 心愿单商品列表
        $products = \Biz\service\springHomeDecActivity\WishListService::getWishProducts($this->_uid);
        shuffle($products);
        foreach ($products as $product) {
            if ($product['winning'] > 0) continue;
            if (!CSpringHomeGift::giftExists($product['product_id'])) continue;
            $this->_product = MSpringHomeDecProduct::dataSelectInfo(['product_id' => $product['product_id']]);
            break;
        }
    }

    public static function getUserLotteryTimes($uid)
    {
        return CSpringHomeLottery::userTimes($uid, self::$_day_times);
    }

}